﻿Imports System.Security.Principal
Imports System.Reflection
Imports System.IO
Imports System.Deployment.Application
Imports System.Text


Public Class MainForm

#Region "win32DLLs"
    Declare Function WNetGetConnection Lib "mpr.dll" Alias "WNetGetConnectionA" (ByVal lpszLocalName As String, _
     ByVal lpszRemoteName As String, ByRef cbRemoteName As Integer) As Integer
#End Region

#Region "Constants"
    Public Const Version = "1.1.0"
#End Region

#Region "Globals"
    Public UserDocs As String = System.Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments) & "/DriveMappy"
    Public log As New Logger
    Public DbOps As New XMLOps
    Public MainDV As New DataView
    Public ValidDrives As New List(Of String)
    Public AutoMapCompleted As Boolean = False
    Public AsAdmin As Boolean = False

    Public MountErrorCodes As New Dictionary(Of Integer, String) From {{0, "NO_ERROR"},
                                                {53, "ERROR_BAD_NETPATH"},
                                                {65, "ERROR_NETWORK_ACCESS_DENIED"},
                                                {54, "ERROR_NETWORK_BUSY"},
                                                {5, "ERROR_ACCESS_DENIED"},
                                                {85, "ERROR_ALREADY_ASSIGNED"},
                                                {66, "ERROR_BAD_DEV_TYPE"},
                                                {1200, "ERROR_BAD_DEVICE"},
                                                {67, "ERROR_BAD_NET_NAME"},
                                                {1206, "ERROR_BAD_PROFILE"},
                                                {1204, "ERROR_BAD_PROVIDER"},
                                                {170, "ERROR_BUSY"},
                                                {1223, "ERROR_CANCELLED"},
                                                {1205, "ERROR_CANNOT_OPEN_PROFILE"},
                                                {1202, "ERROR_DEVICE_ALREADY_REMEMBERED"},
                                                {1208, "ERROR_EXTENDED_ERROR"},
                                                {86, "ERROR_INVALID_PASSWORD"},
                                                {1203, "ERROR_NO_NET_OR_BAD_PATH"},
                                                {2250, "ERROR_DRIVE_ALREADY_UNMAPPED"}}


#End Region

    Private Sub MainForm_FormClosing(sender As Object, e As FormClosingEventArgs) Handles Me.FormClosing
        NotifyIcon1.Visible = False
        NotifyIcon1.Dispose()

        If AsAdmin Then
            My.Settings.FormSize = Me.Size
            My.Settings.FormLoc = Me.Location

            DbOps.SaveXML(MainDS, UserDocs & "/data.xml")
            My.Settings.Save()
        End If


    End Sub

    Private Sub Mappy_Load(sender As Object, e As EventArgs) Handles MyBase.Load

        EnsureAdmin()

        If My.Settings.LaunchToTray = True Then
            Me.Opacity = 0
            Me.Hide()
            Me.ShowInTaskbar = False
        End If

        Me.Font = My.Settings.GUIFont
        Me.Text = "Drive Mappy - V" & Version

        Initialise()

        If My.Settings.MapAtLaunch = True Then AutoMapProcess()

    End Sub

    Private Sub Initialise()

        EnsureDocumentsGroup()

        StartLog()

        InitialiseVars()

        SetupDGV()

        SettsToForm()

        AutoSizeForm()

    End Sub

    Private Sub AutoSizeForm()

        Me.Location = My.Settings.FormLoc
        Me.Size = My.Settings.FormSize

        If Me.Location.X < 0 Then Me.Location = New Point(10, 10)
        If Me.Location.Y < 0 Then Me.Location = New Point(10, 10)

        If Me.Size.Height < 50 Then Me.Size = New Size(1000, 200)
        If Me.Size.Width < 50 Then Me.Size = New Size(100, 200)

    End Sub

    Private Sub SettsToForm()

        _DebugChB.Checked = My.Settings._debug
        LaunchToTrayChB.Checked = My.Settings.LaunchToTray
        LinkAdminChB.Checked = My.Settings.LinkUserAdmin
        _RunSartChB.Checked = My.Settings.LaunchAtStartup
        _MapStartBT.Checked = My.Settings.MapAtLaunch
        ClearOnAutoChB.Checked = My.Settings.ClearOnAuto

    End Sub

#Region "Datagrid"

    Private Sub SetupDGV()

        With MainDGV
            .AutoSizeColumnsMode = DataGridViewAutoSizeColumnsMode.AllCells
            '.Columns.Add(New DataGridViewImageColumn With {.Image = My.Resources.ledred,
            '        .ImageLayout = DataGridViewImageCellLayout.Zoom,
            '         .Name = "Mapped", .HeaderText = ""})
            .Columns.Add(New DataGridViewButtonColumn With {.Text = "...",
                                 .UseColumnTextForButtonValue = True,
                                 .Name = "Browse", .HeaderText = ""})
            .Columns.Add(New DataGridViewComboBoxColumn With {.DataPropertyName = "Drive", .Visible = True,
                             .Name = "Drive",
                             .DataSource = ValidDrives,
                             .FlatStyle = FlatStyle.Popup})
            .DataSource = MainDV

            If My.Settings._debug = False Then
                .Columns("ID").ReadOnly = True
                .Columns("ID").Visible = False
            End If

            .Columns("UNCPath").DisplayIndex = 0
            .Columns("Drive").DisplayIndex = 0

            With .Columns("Mapped")
                .HeaderText = "Map'd"
                .ReadOnly = True
                .DisplayIndex = 0
            End With

            .Columns("Priority").DisplayIndex = MainDGV.ColumnCount - 1
            '.AutoSizeColumnsMode = DataGridViewAutoSizeColumnsMode.None
            .Columns("Browse").AutoSizeMode = DataGridViewAutoSizeColumnMode.AllCells
        End With
    End Sub

    Private Sub MainDGVCellClick(sender As Object, e As DataGridViewCellEventArgs) Handles MainDGV.CellContentClick
        log.decho("DGV Cell Click")
        If TypeOf MainDGV.Columns(e.ColumnIndex) Is DataGridViewButtonColumn AndAlso e.RowIndex >= 0 Then
            With FBD1
                .Description = "Choose a location to set the UNC..."
                '.SelectedPath = ROMSFolderTB.Text
            End With
            Dim result As Windows.Forms.DialogResult = FBD1.ShowDialog()
            If result = Windows.Forms.DialogResult.OK Then
                Dim filepath As New Uri(FBD1.SelectedPath)
                If filepath.IsUnc Then
                    MainDGV.Rows(e.RowIndex).Cells("UNCPath").Value = FBD1.SelectedPath
                    ' MsgBox("The slected path must begin with a drive letter. No UNC (network) paths allowed. If you're wanting to use a network path, use a mapped network drive instead. Read the FAQa on the Codeplex documentation for more info on this.", MsgBoxStyle.Exclamation, "ERROR: UNC path chosen")
                    Return
                Else
                    MainDGV.Rows(e.RowIndex).Cells("UNCPath").Value = GetUNCPath(FBD1.SelectedPath)
                End If
            End If
        End If
    End Sub

    Private Sub MAINDGV_RowValidating(sender As Object, e As DataGridViewCellEventArgs) Handles MainDGV.CellValueChanged
        log.decho("row validating...")
        If e.RowIndex < 1 Or e.ColumnIndex < 1 Then Return

        If String.IsNullOrEmpty(CStr(MainDGV.Rows(e.RowIndex).Cells("Drive").FormattedValue)) Then
            log.decho("Drive null")
            If DrivesFilterCB.Text = "All" Then
                MainDGV.Rows(e.RowIndex).Cells("Drive").Value = ValidDrives(0)
            Else
                MainDGV.Rows(e.RowIndex).Cells("Drive").Value = DrivesFilterCB.Text
            End If
        End If

        If String.IsNullOrEmpty(CStr(MainDGV.Rows(e.RowIndex).Cells("UNCPath").FormattedValue)) Then
            MainDGV.Rows(e.RowIndex).Cells("UNCPath").Value = "\\localhost\c$\Windows\"
        End If

        If String.IsNullOrEmpty(CStr(MainDGV.Rows(e.RowIndex).Cells("Priority").FormattedValue)) Then
            MainDGV.Rows(e.RowIndex).Cells("Priority").Value = 1
        End If

    End Sub

    Private Sub MainDGVError(sender As Object, e As DataGridViewDataErrorEventArgs) Handles MainDGV.DataError
        If TypeOf MainDGV.Columns(e.ColumnIndex) Is DataGridViewComboBoxColumn AndAlso e.RowIndex >= 0 Then
            e.Cancel = True
            'MainDGV(e.ColumnIndex, e.RowIndex).Value = 0
            'MainDGV(e.ColumnIndex, e.RowIndex).ReadOnly = True
        End If
    End Sub

#End Region

    Private Function NotNull(Of T)(ByVal Value As T, ByVal DefaultValue As T) As T

        If Value Is Nothing OrElse IsDBNull(Value) Then
            Return DefaultValue
        Else
            Return Value
        End If
    End Function



    Private Sub InitialiseVars()
        log.echo("", "initialising variables")

        ' DATABASE
        log.echo("Database:")
        If File.Exists(UserDocs & "/data.xml") = False Then
            log.echo("XML doesn't exist - create default.")
            Dim newrow As DataRow = MainDS.Tables("Drives").NewRow
            newrow.Item("UNCPath") = "\\localhost\"
            newrow.Item("Drive") = "G"
            newrow.Item("Priority") = 1
            MainDS.Tables("Drives").Rows.Add(newrow)
            DbOps.SaveXML(MainDS, UserDocs & "/data.xml")
        Else
            log.echo("XML exists")
            DbOps.LoadXML(MainDS, UserDocs & "/data.xml")
        End If
        log.echo("Database Loaded")

        ' CLEAR ANY MAPPED BOOLEANS
        For Each drow As DataRow In MainDS.Tables("Drives").Rows
            drow.Item("Mapped") = False
        Next

        'CHANGELOG
        File.WriteAllText(UserDocs & "/changelog.txt", My.Resources.ChangeLog)

        'DATAVIEW
        MainDV = New DataView(MainDS.Tables("Drives"))
        MainDV.Sort = "Drive ASC"

        'Valid Drives List
        MakeValidDrivesList()

        'Dirve filter DD:
        DrivesFilterCB.Items.Add("All")
        DrivesFilterCB.Items.AddRange(ValidDrives.ToArray)
        DrivesFilterCB.SelectedIndex = 0

    End Sub

    Private Sub MakeValidDrivesList()
        log.echo("Constructing drives list...")
        ValidDrives.Clear()
        For Each c In "ABCDEFGHIJKLMNOPQRSTUVWXYZ".ToCharArray()
            ValidDrives.Add(c.ToString)
        Next

        Dim allDrives() As DriveInfo = DriveInfo.GetDrives()

        Dim d As DriveInfo
        For Each d In allDrives
            log.decho(d.DriveType.ToString, d.Name)
            Select Case d.DriveType.ToString
                Case "CDRom"
                    ValidDrives.Remove((d.Name).Substring(0, 1))
                Case "Fixed"
                    ValidDrives.Remove((d.Name).Substring(0, 1))
                Case "Ram"
                    ValidDrives.Remove((d.Name).Substring(0, 1))
                Case "Removable"
                    ValidDrives.Remove((d.Name).Substring(0, 1))
                Case "Unknown"
                    ValidDrives.Remove((d.Name).Substring(0, 1))
            End Select
        Next

        Dim drivelist As String = ""
        For Each drive In ValidDrives
            drivelist = drivelist & drive & ", "
        Next
        log.echo("Drives list complete. Free/remappable Drives:")
        log.echo(drivelist)

    End Sub

    Private Sub StartLog()

        log.Initialize("DriveMappy", Version, UserDocs & "/log.log", My.Settings._debug)
        log.line()
        log.echo(DateTime.Now.ToString("MMM ddd d HH:mm yyyy"), "started")
        log.decho("Set in settings.", "Debug mode On")

    End Sub

    Private Sub EnsureDocumentsGroup()
        If Not Directory.Exists(UserDocs) Then
            Directory.CreateDirectory(UserDocs)
        End If
    End Sub


    Private Sub EnsureAdmin()

        Dim wi = WindowsIdentity.GetCurrent()
        Dim wp = New WindowsPrincipal(wi)
        Dim runAsAdmin As Boolean = wp.IsInRole(WindowsBuiltInRole.Administrator)

        If Not runAsAdmin Then
            ' MsgBox("not admin")
            ' It is not possible to launch a ClickOnce app as administrator directly,
            ' so instead we launch the app as administrator in a new process.
            Dim processInfo = New ProcessStartInfo(Assembly.GetExecutingAssembly().CodeBase)

            ' The following properties run the new process as administrator
            processInfo.UseShellExecute = True
            processInfo.Verb = "runas"

            ' Start the new process
            Try
                Process.Start(processInfo)
            Catch generatedExceptionName As Exception
                ' The user did not allow the application to run as administrator
                MessageBox.Show("Sorry, but I don't seem to be able to start " + "this program with administrator rights!")
            End Try

            ' Shut down the current process
            Application.[Exit]()
        Else
            'MsgBox("admin")
            ' We are running as administrator
            'Application.EnableVisualStyles()
            ''   Application.SetCompatibleTextRenderingDefault(False)
            'Application.Run(New Form())
            AsAdmin = True
        End If
    End Sub


    Private Sub GoBT_Click(sender As Object, e As EventArgs) Handles GoBT.Click

        Dim selectedRowCount As Integer = _
            MainDGV.Rows.GetRowCount(DataGridViewElementStates.Selected)
        If selectedRowCount < 1 Then
            MsgBox("To map a network drive, please select it via the row header",
                   MsgBoxStyle.Exclamation, "Please select a row...")
            Return
        End If

        If MainDGV.SelectedRows(0).IsNewRow Then
            MsgBox("You cannot map this row - it is the add new drive row.", MsgBoxStyle.Exclamation, "Select a different drive...")
            Return
        End If

        Dim selrow() As DataRow = MainDS.Tables("Drives").Select("ID = " &
                                        MainDGV.SelectedRows(0).Cells("ID").Value.ToString)

        Dim MapDrive As New DriveMapper
        With MapDrive
            .DriveLetter = selrow(0).Item("Drive").ToString
            .UNCPath = selrow(0).Item("UNCPath").ToString
            If selrow(0).Item("Username").ToString <> "" Then .UserName = selrow(0).Item("Username").ToString
            If selrow(0).Item("Password").ToString <> "" Then .UNPassword = selrow(0).Item("Password").ToString
        End With

        Dim MapResult = MapDrive.MapDrive()

        Dim ErrOut As String = Nothing
        If Not (MountErrorCodes.TryGetValue(CInt(MapResult), ErrOut)) Then
            ErrOut = "Unknown Error: " & MapResult
        End If

        If MapResult = 0 Then
            MsgBox("Drive successfully mapped.", MsgBoxStyle.Information)
            selrow(0).Item("Mapped") = True
        Else
            MsgBox("Error mapping drive: " & vbCr & vbCr & ErrOut, MsgBoxStyle.Exclamation)
        End If

    End Sub


    Private Sub _unmapBT_Click(sender As Object, e As EventArgs) Handles _unmapBT.Click
        Dim selectedRowCount As Integer = _
           MainDGV.Rows.GetRowCount(DataGridViewElementStates.Selected)
        If selectedRowCount < 1 Then
            MsgBox("To unmap a network drive, please select it via the row header",
                   MsgBoxStyle.Exclamation, "Please select a row...")
            Return
        End If

        If MainDGV.SelectedRows(0).IsNewRow Then
            MsgBox("You cannot unmap this row - it is the add new drive row.", MsgBoxStyle.Exclamation, "Select a different drive...")
            Return
        End If

        Dim MapDrive As New DriveMapper

        Dim selrow() As DataRow = MainDS.Tables("Drives").Select("ID = " &
                                     MainDGV.SelectedRows(0).Cells("ID").Value.ToString)

        With MapDrive
            .DriveLetter = selrow(0).Item("Drive").ToString
        End With

        Dim UnMapResult = MapDrive.UnMapDrive()
        Dim ErrOut As String = Nothing
        If Not (MountErrorCodes.TryGetValue(CInt(UnMapResult), ErrOut)) Then
            ErrOut = "Unknown Error: " & UnMapResult
        End If

        If UnMapResult = 0 Then
            MsgBox("Drive successfully unmapped.", MsgBoxStyle.Information)
            'Uncheck "Mapped"
            For Each drow As DataRow In MainDS.Tables("Drives").Rows
                If drow.Item("Drive").ToString = selrow(0).Item("Drive").ToString Then
                    drow.Item("Mapped") = False
                End If
            Next
        Else
            MsgBox("Error unmapping drive: " & vbCr & vbCr & ErrOut,
                   MsgBoxStyle.Exclamation)
        End If

    End Sub



    Private Sub _RunSartChB_CheckedChanged(sender As Object, e As EventArgs) Handles _RunSartChB.CheckedChanged
        If _RunSartChB.Checked = True Then
            My.Computer.Registry.CurrentUser.OpenSubKey("SOFTWARE\Microsoft\Windows\CurrentVersion\Run", True).SetValue(Application.ProductName, Application.ExecutablePath)
            My.Settings.LaunchAtStartup = True
        Else
            My.Computer.Registry.CurrentUser.OpenSubKey("SOFTWARE\Microsoft\Windows\CurrentVersion\Run", True).DeleteValue(Application.ProductName)
            My.Settings.LaunchAtStartup = False
        End If
        My.Settings.Save()
    End Sub

    Private Sub LinkAdminChB_CheckedChanged(sender As Object, e As EventArgs) Handles LinkAdminChB.CheckedChanged
        If LinkAdminChB.Checked = True Then
            My.Computer.Registry.LocalMachine.OpenSubKey("SOFTWARE\Microsoft\Windows\CurrentVersion\Policies\System",
                                                        True).SetValue("EnableLinkedConnections", 1)
            My.Settings.LinkUserAdmin = True
        Else
            My.Computer.Registry.LocalMachine.OpenSubKey("SOFTWARE\Microsoft\Windows\CurrentVersion\Policies\System",
                                                        True).DeleteValue("EnableLinkedConnections")
            My.Settings.LinkUserAdmin = False
        End If
        My.Settings.Save()
    End Sub


    Private Sub _DebugChB_CheckedChanged(sender As Object, e As EventArgs) Handles _DebugChB.CheckedChanged
        If _DebugChB.Checked = True Then
            My.Settings._debug = True
        Else
            My.Settings._debug = False
        End If
        My.Settings.Save()
    End Sub

    Private Sub SetingsBT_Click(sender As Object, e As EventArgs) Handles SetingsBT.Click
        If TopSplit.Panel2Collapsed = False Then
            TopSplit.Panel2Collapsed = True
        Else
            TopSplit.Panel2Collapsed = False
        End If


    End Sub


    Private Sub DrivesFilterCB_SelectedIndexChanged(sender As Object, e As EventArgs) Handles DrivesFilterCB.SelectedIndexChanged
        If DrivesFilterCB.Text = "All" Then
            MainDV.RowFilter = ""
            MainDV.Sort = "Drive, Priority"
        Else
            MainDV.RowFilter = "Drive = '" & DrivesFilterCB.Text & "'"
            MainDV.Sort = "Drive, Priority"
        End If
    End Sub

    Private Function GetUNCPath(ByVal sFilePath As String) As String

        Dim allDrives() As DriveInfo = DriveInfo.GetDrives()
        Dim d As DriveInfo
        Dim DriveType, Ctr As Integer
        Dim DriveLtr, UNCName As String
        Dim StrBldr As New StringBuilder

        If sFilePath.StartsWith("\\") Then Return sFilePath

        UNCName = Space(160)
        GetUNCPath = ""

        DriveLtr = sFilePath.Substring(0, 3)

        For Each d In allDrives
            If d.Name = DriveLtr Then
                DriveType = d.DriveType
                Exit For
            End If
        Next

        If DriveType = 4 Then

            Ctr = WNetGetConnection(sFilePath.Substring(0, 2), UNCName, UNCName.Length)

            If Ctr = 0 Then
                UNCName = UNCName.Trim
                For Ctr = 0 To UNCName.Length - 1
                    Dim SingleChar As Char = UNCName(Ctr)
                    Dim asciiValue As Integer = Asc(SingleChar)
                    If asciiValue > 0 Then
                        StrBldr.Append(SingleChar)
                    Else
                        Exit For
                    End If
                Next
                StrBldr.Append(sFilePath.Substring(2))
                GetUNCPath = StrBldr.ToString
            Else
                MsgBox("Cannot Retrieve UNC path", MsgBoxStyle.Critical)
            End If
        ElseIf DriveType = 3 Then
            If Ctr = 0 Then
                UNCName = UNCName.Trim
                For Ctr = 0 To UNCName.Length - 1
                    Dim SingleChar As Char = UNCName(Ctr)
                    Dim asciiValue As Integer = Asc(SingleChar)
                    If asciiValue > 0 Then
                        StrBldr.Append(SingleChar)
                    Else
                        Exit For
                    End If
                Next
                StrBldr.Append(sFilePath.Substring(2))
                GetUNCPath = "\\localhost" & "\" & DriveLtr.Substring(0, 1) & "$" & StrBldr.ToString
            Else
                MsgBox("Cannot Retrieve UNC path", MsgBoxStyle.Critical)
            End If
        Else
            MsgBox("You chose either a CDRom, Ram, Removable or Unknown Drive Type. You must choose either a local fixed drive or a network drive.",
                   MsgBoxStyle.Critical)
            GetUNCPath = "\\localhost" & StrBldr.ToString

        End If

    End Function

    Private Sub AddBT_Click(sender As Object, e As EventArgs) Handles AddBT.Click
        Dim newrow As DataRow = MainDS.Tables("Drives").NewRow
        newrow.Item("UNCPath") = "\\localhost\C$\Windows"

        Dim drive As String
        If DrivesFilterCB.Text = "All" Then
            drive = ValidDrives(0)
        Else
            drive = DrivesFilterCB.Text
        End If
        newrow.Item("Drive") = drive

        Dim priority As Integer = 1
        Dim drivemaps() As DataRow = MainDS.Tables("Drives").Select("Drive = '" & drive & "'")
        For Each drivemap As DataRow In drivemaps
            ' log.decho("Drive iteration priority: " & CInt(drivemap.Item("Priority")))
            If CInt(drivemap.Item("Priority")) >= priority Then
                'log.decho("HOQ than last int. Changing to: " & CInt(drivemap.Item("Priority")) + 1)
                priority = CInt(drivemap.Item("Priority")) + 1
            End If

        Next
        newrow.Item("Priority") = priority
        MainDS.Tables("Drives").Rows.Add(newrow)

        MainDS.AcceptChanges()

        DbOps.SaveXML(MainDS, UserDocs & "/data.xml")


    End Sub


    Private Sub _MapStartBT_CheckedChanged(sender As Object, e As EventArgs) Handles _MapStartBT.CheckedChanged
        If _MapStartBT.Checked Then
            My.Settings.MapAtLaunch = True
        Else
            My.Settings.MapAtLaunch = False
        End If
        My.Settings.Save()
    End Sub

    Private Sub LaunchToTrayChB_CheckedChanged(sender As Object, e As EventArgs) Handles LaunchToTrayChB.CheckedChanged
        If LaunchToTrayChB.Checked Then
            My.Settings.LaunchToTray = True
        Else
            My.Settings.LaunchToTray = False
        End If
        My.Settings.Save()
    End Sub

    Private Sub CloseToolStripMenuItem_Click(sender As Object, e As EventArgs) Handles CloseToolStripMenuItem.Click

        Me.Close()

    End Sub

    Private Sub NotifyIcon1_MouseDoubleClick(sender As Object, e As MouseEventArgs) Handles NotifyIcon1.MouseDoubleClick
        Me.Opacity = 1
        Me.Show()
        Me.WindowState = FormWindowState.Normal
        Me.ShowInTaskbar = True
    End Sub

    Private Sub AutoMapProcess()
        log.line()
        log.echo("", "starting automap")
        Dim DriveDV As New DataView(MainDS.Tables("Drives"))

        For Each DriveLetter As String In ValidDrives

            DriveDV.RowFilter = "Drive = '" & DriveLetter & "'"

            If DriveDV.Count > 0 Then
                log.echo(DriveLetter & " Drive has maps: " & DriveDV.Count)

                'Unmap existing if settings will it
                Dim MapDrive As New DriveMapper
                Dim ErrOut As String = ""
                If My.Settings.ClearOnAuto = True Then
                    log.echo("Autoclear maps selected. Attempt Unmapping this drive")
                    'Unmap
                    With MapDrive
                        .DriveLetter = DriveLetter
                    End With

                    Dim UnMapResult = MapDrive.UnMapDrive()

                    If Not (MountErrorCodes.TryGetValue(CInt(UnMapResult), ErrOut)) Then
                        ErrOut = "Unknown Error: " & UnMapResult
                    End If

                    If UnMapResult = 0 Then
                        log.echo("Drive successfully unmapped.")
                        For Each dgvrow As DataGridViewRow In MainDGV.Rows
                            If dgvrow.Cells("Drive").Value.ToString = DriveLetter.ToString Then
                                dgvrow.Cells("Mapped").Value = False

                            End If
                        Next
                    Else
                        log.echo("Error unmapping drive: " & ErrOut)
                    End If
                End If

                DriveDV.Sort = "Priority ASC"

                For Each DriveMap As DataRow In DriveDV.ToTable.Rows

                    log.echo("Attempting map [" & DriveMap.Item("Priority").ToString & "] : " & DriveMap.Item("UNCPath").ToString)

                    'Map
                    With MapDrive
                        .DriveLetter = DriveMap.Item("Drive").ToString
                        .UNCPath = DriveMap.Item("UNCPath").ToString
                        If DriveMap.Item("Username").ToString <> "" Then .UserName = DriveMap.Item("Username").ToString
                        If DriveMap.Item("Password").ToString <> "" Then .UNPassword = DriveMap.Item("Password").ToString
                    End With

                    Dim MapResult = MapDrive.MapDrive()

                    If Not (MountErrorCodes.TryGetValue(CInt(MapResult), ErrOut)) Then
                        ErrOut = "Unknown Error: " & MapResult
                    End If

                    If MapResult = 0 Then
                        log.echo("Drive successfully mapped. Skipping other map attempts for this drive.")
                        For Each dgvrow As DataGridViewRow In MainDGV.Rows
                            'log.echo(dgvrow.Cells("ID").Value.ToString & "  ||  " & DriveMap.Item("ID").ToString)
                            If dgvrow.Cells("ID").Value.ToString = DriveMap.Item("ID").ToString Then
                                'log.echo("DriveMap set to green")
                                dgvrow.Cells("Mapped").Value = True
                            End If
                        Next
                        Exit For
                    Else
                        log.echo("Error mapping drive: " & ErrOut & ". Moving onto next map...")
                    End If
                Next
                log.echo("")
            End If

        Next

        If Me.Visible = True Then MsgBox("Autorun completed successfully", MsgBoxStyle.Information)

        AutoMapCompleted = True
        CTBAutorun.Image = My.Resources.Green_light
        CTBAutorun.Text = "Autorun Completed"
        log.echo("End of Automap process")
        log.line()


    End Sub

    Private Sub MapAllBT_Click(sender As Object, e As EventArgs) Handles MapAllBT.Click
        AutoMapProcess()
    End Sub

    Private Sub ClearOnAutoChB_CheckedChanged(sender As Object, e As EventArgs) Handles ClearOnAutoChB.CheckedChanged
        If ClearOnAutoChB.Checked Then
            My.Settings.ClearOnAuto = True
        Else
            My.Settings.ClearOnAuto = False
        End If
        My.Settings.Save()
    End Sub


  
  
    Private Sub FontBT_Click(sender As Object, e As EventArgs) Handles FontBT.Click
        With FontDialog1
            .Font = Me.Font
            .ShowEffects = True
        End With
        If FontDialog1.ShowDialog = Windows.Forms.DialogResult.OK Then
            Me.Font = FontDialog1.Font
            My.Settings.GUIFont = FontDialog1.Font
        End If

    End Sub

    Private Sub LogBT_Click(sender As Object, e As EventArgs) Handles LogBT.Click
        Try
            Process.Start(UserDocs & "/log.log")
        Catch
            MsgBox("Sorry, can't locate the log.", MsgBoxStyle.Exclamation)
        End Try

    End Sub

  
    Private Sub ShowToolStripMenuItem_Click(sender As Object, e As EventArgs) Handles ShowToolStripMenuItem.Click
        Me.Opacity = 1
        Me.Show()
        Me.WindowState = FormWindowState.Normal
        Me.ShowInTaskbar = True
    End Sub

    Private Sub ContextMenuStrip1_Opening(sender As Object, e As System.ComponentModel.CancelEventArgs) Handles ContextMenuStrip1.Opening
        'Clear existing drive maps:
        'MsgBox(ContextMenuStrip1.Items.Count)
        If ContextMenuStrip1.Items.Count > 6 Then
            For i As Integer = ContextMenuStrip1.Items.Count - 1 To 6 Step -1
                ContextMenuStrip1.Items.RemoveAt(i)
            Next
        End If

        For Each drow As DataRow In MainDS.Tables("Drives").Rows
            If CBool(drow.Item("Mapped")) Then
                Dim cmsitem As New ToolStripMenuItem
                cmsitem.Text = drow.Item("Drive").ToString & ": " & drow.Item("UNCPath").ToString
                cmsitem.Tag = "drive"
                cmsitem.Enabled = False
                ContextMenuStrip1.Items.Add(cmsitem)
            End If
        Next
    End Sub

    'Private Sub MainDGV_KeyPress(sender As Object, e As System.Windows.Forms.KeyPressEventArgs) Handles MainDGV.KeyPress
    '    If MainDGV.Columns(MainDGV.CurrentCell.ColumnIndex).HeaderText = "Priority" Then
    '        If (Char.IsDigit(e.KeyChar)) Then
    '            'this is a number
    '        Else
    '            e.Handled = True
    '        End If
    '    End If

    'End Sub

    Private Sub DataGridView1_EditingControlShowing(ByVal sender As Object, ByVal e As System.Windows.Forms.DataGridViewEditingControlShowingEventArgs) Handles MainDGV.EditingControlShowing

        If MainDGV.Columns(MainDGV.CurrentCell.ColumnIndex).HeaderText = "Priority" Then

            AddHandler CType(e.Control, TextBox).KeyPress, AddressOf TextBox_keyPress

        End If

    End Sub

    Private Sub TextBox_keyPress(ByVal sender As Object, ByVal e As KeyPressEventArgs)

        'If Char.IsDigit(CChar(CStr(e.KeyChar))) = False Then e.Handled = True
        If e.KeyChar <> ControlChars.Back Then
            e.Handled = Not (Char.IsDigit(e.KeyChar))
        End If

    End Sub

End Class
